import sys
import socket
from threading import Thread

import traceback

import socketserver

import shell

import logger
from logger import log


class BaseRequestHandler(socketserver.BaseRequestHandler):
    def setup(self):
        self.server.clientsocket[self.client_address] = self.request
        log.warning("%s connect successful"%(str(self.client_address)))
    def finish(self):
        del self.server.clientsocket[self.client_address]
        log.warning("%s disconnect"%(str(self.client_address)))
    def handle(self):
        try:
            while True:
                data = self.recv()
                if self.recv_handle(data):
                    break
        except ConnectionAbortedError as e:
            log.error("%s:Exception-(%s)"%(str(self.client_address), str(e)))
        except Exception as e:
            log.error("%s:Exception-(%s)(%s)\n%s"%(str(self.client_address), str(type(e)), str(e), traceback.format_exc()))

    def recv_handle(self, data):
        result = False
        if data == "exit".encode("utf-8"):
            result = True
        else:
            self.sendall(data)
        return result
    def recv(self):
        data = self.request.recv(4096)
        if len(data) <= 0:
            raise ConnectionAbortedError("对方断开连接")
        # log.debug("%s:\n"%(str(self.client_address)) + str(data))
        return data
    def sendall(self, data):
        self.request.sendall(data)

class ThreadingTCPServer(socketserver.ThreadingTCPServer):
    
    def __init__(self, server_address=("localhost",8000), RequestHandlerClass=BaseRequestHandler, bind_and_activate=True,**argv):
        self.clientsocket = {}
        self.clients = {}
        self.argv = argv
        super().__init__(server_address, RequestHandlerClass, bind_and_activate)
    
    def disconnect_all(self):
        for address in self.clientsocket:
            self.clientsocket[address].close()
        
    def disconnect(self, socket_address):
        if socket_address in self.clientsocket:
            self.clientsocket[socket_address].close()
'''
    def process_request(self, request, client_address):
        """Start a new thread to process the request."""
        t = Thread(target = self.process_request_thread,
                   args = (request, client_address),
                   name = "Client:(%s)(%s)"%(str(self.server_address), str(client_address)))
        t.daemon = self.daemon_threads
        if not t.daemon and self.block_on_close:
            if self._threads is None:
                self._threads = []
            self._threads.append(t)
        t.start()
'''

class TCPServer:

    def __init__(self, server_address=("localhost",8000), RequestHandlerClass=BaseRequestHandler,isAutoStart=True,**argv):
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.server = None
        self.argv = argv
        if isAutoStart:
            self.start()

    def thread_serve_forever(self):
        self.server.serve_forever()

    def start(self):
        if self.server is None:
            self.server = ThreadingTCPServer(server_address=self.server_address, RequestHandlerClass=self.RequestHandlerClass,**self.argv)

            self.disconnect_all = self.server.disconnect_all
            self.disconnect = self.server.disconnect

            self.tid = Thread(target=self.thread_serve_forever, name="Server:(%s)"%(str(self.server_address)))
            self.tid.start()
            log.warning("%s Start"%(str(self.server_address)))

    def stop(self):
        if not self.server is None:
            
            server = self.server
            self.server = None

            server.disconnect_all()
            server.shutdown()
            
            self.tid = None
            self.disconnect_all = None
            self.disconnect = None
            log.warning("%s Stop"%(str(self.server_address)))

    def get_client(self):
        clients = []
        if not self.server is None:
            for client in self.server.clientsocket:
                clients.append(client)
        return clients
    
    def get_handle(self):
        if not self.server is None:
            return self.server.clients
        return {}
    
    def isStart(self):
        return self.server != None

    def __enter__(self):
        self.start()
        print("__enter__")
        return self
    def __exit__(self,exc_type,exc_value,exc_trackback):
        self.stop()
        print(exc_type)
        print(exc_value)
        print(exc_trackback)


class ServerTestShell(shell.shell):
    # use_rawinput = 0
    def do_start(self, arg):
        global server
        server.start()
    def do_stop(self, arg):
        global server
        server.stop()
    def do_client(self, arg):
        global server
        clients = server.get_client()
        string = "\n"
        for index in range(0, len(clients)):
            string += "%d. %s\n"%(index, str(clients[index]))
        log.info(string)
    def do_disconnect(self, arg):
        server.disconnect_all()

if __name__ == '__main__':
    with TCPServer(server_address=("192.168.1.78",12006)) as server:
        sh = ServerTestShell()
        sh.cmdloop()
    log.info("退出")


'''
if __name__ == '__main__':
    server = TCPServer()
    sh = ServerTestShell()
    sh.cmdloop()
    server.stop()
    log.info("退出")
'''



